package com.work.ioc;

import com.work.annotation.Autowired;
import com.work.annotation.Service;
import com.work.ioc.iocUtils.IocUtils;

import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @program: spring-work
 * @description
 * @author: luffy
 * @create: 2020-07-08 14:41
 */
public class ApplicationContext {
    private String packageName = "com/work";
    private static Set<Class<?>> classSet = new HashSet<>();
    private  Map<String, Object> ioc = new ConcurrentHashMap<>();

    public ApplicationContext (){
        try {
            refresh();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public void refresh() throws Exception {
        List<String> list = IocUtils.getClassNameList(packageName);
        getClassSet(list);
        parseClass(classSet);
    }

    private void parseClass(Set<Class<?>> classSet) throws Exception {
        /**
         * 遍历所有注解了Service的类
         */
        for (Class<?> clazz : classSet) {
            /**
             * 获取当前class的所有字段判断是否注解了Autowired
             */
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(Autowired.class)) {
                    field.setAccessible(true);
                    //获取字段类型
                    Class<?> fieldType = field.getType();

                    for (Class<?> aClass : classSet) {
                        if (aClass == fieldType) {
                            Object bean = clazz.newInstance();
                            field.set(bean, aClass.newInstance());
                            ioc.put(clazz.getSimpleName(), bean);
                        }
                        //遍历class是否有fieldType子类
                        //获取接口s
                        Class<?>[] interfaces = aClass.getInterfaces();
                        //遍历接口
                        if (interfaces != null) {
                            for (Class<?> anInterface : interfaces) {
                                if (anInterface == fieldType) {
                                    Object bean = clazz.newInstance();
                                    field.set(bean, aClass.newInstance());
                                    ioc.put(clazz.getSimpleName(), bean);
                                }
                            }
                        }else {
                            continue;
                        }

                    }


                }
            }
        }

    }

    private static void getClassSet(List<String> classNameList) {
        for (String className : classNameList) {
            try {
                Class<?> aClass = Class.forName(className);
                if (aClass.isAnnotationPresent(Service.class)) {
                    classSet.add(aClass);
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }





    public Object getBean(String beanName) {
        return ioc.get(beanName);
    }


    public Map<String, Object> getIoc() {
        return ioc;
    }

    public static Set<Class<?>> getClassSet() {
        return classSet;
    }
}
